<!DOCTYPE html>
<script src="../../resources/js-test.js"></script>
<script src="../../resources/gc.js"></script>
<body>
<script>
description('Tests that the internals.observeGC hook works.');

window.jsTestIsAsync = true;

function runAsyncGC() {
  return new Promise(resolve => asyncGC(resolve));
}

shouldBe('typeof internals.observeGC', '"function"',
         'this test requires window.internals');

var valueA, observationA, observationB, observationC;

(async () => {
  // "Generic Kid's Movie III": ... where nobody dies.

  // Do initialization work in an inner function to avoid references to
  // objects remaining live on this function's stack frame.
  // (http://crbug.com/595672/).
  (function () {
    valueA = {};
    observationA = internals.observeGC(valueA);
  })();

  await runAsyncGC();
  shouldBeFalse('observationA.wasCollected');
  // value ineligible for GC should not be flagged as collected
  valueA = null;
  observationA = null;

  // "Romeo and GCuliet": Romeo JavaScript finds G.uliet C.apulet and dies.

  // Do initialization work in an inner function to avoid references to
  // objects remaining live on this function's stack frame.
  // (http://crbug.com/595672/).
  (function() {
    var valueB = {};
    observationB = internals.observeGC(valueB);
  })();

  await runAsyncGC();
  shouldBeTrue('observationB.wasCollected');
  // value eligible for GC should be flagged as collected
  observationB = null;

  // "One DOM Tree Hill": A family struggles with the loss of
  // innocence. And a DOM node.

  // Do initialization work in an inner function to avoid references to
  // objects remaining live on this function's stack frame.
  // (http://crbug.com/595672/).
  (function() {
  var valueC = document.createElement('div');
  observationC = internals.observeGC(valueC);
  })();

  await runAsyncGC();
  shouldBeTrue('observationC.wasCollected');
  // DOM node eligible for GC should be flagged as collected
  observationC = null;

  // Now, movies that failed:

  shouldThrow('internals.observeGC(undefined)',
      '"TypeError: value to observe is null or undefined"');
  shouldThrow('internals.observeGC(null)',
    '"TypeError: value to observe is null or undefined"');

  // Try to create objects and observers that will die at once

  // Do initialization work in an inner function to avoid references to
  // objects remaining live on this function's stack frame.
  // (http://crbug.com/595672/).
  (function() {
    var valueD = {};
    var observerD = internals.observeGC(valueD);
    valueD.observer = observerD;
    observerD.observed = valueD;
  })();

  await runAsyncGC();
  testPassed('did not crash');

  finishJSTest();
})();

var successfullyParsed = true;
</script>
